/*
 * RemoteServer.java   0.0.1    28/set/2009
 * 
 * Copyright (c) 2009 mentalsmash.org
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * The use of the Apache License does not indicate that this project is
 * affiliated with the Apache Software Foundation.
 */ 
package org.mentalsmash.tazio.net.cs.client;

import java.io.IOException;
import java.net.InetAddress;

/**
 * Represents a Remote Server.
 * <p>
 * A <tt>RemoteServer</tt> instance can be in one of two states at any time:
 * <ul>
 *   <li>
 *     <strong>Connected State</strong>: if an actual connection (e.g. a socket
 *     connection) with the remote server is established. <br/> When in this state
 *     interactions with the server can be performed using the {@link Connection}
 *     instance retrievable with {@link RemoteServer#getConnection()}.
 *   </li>
 *   <li>
 *     <strong>Disconnected State</strong>: if there is no actual connection to
 *     a remote server. <br /> When in this state you can call {@link #connect(InetAddress,int)}
 *     to try to establish a connection.
 *   </li>
 * </ul>
 * </p>
 * @author Andrea Reale <andrea.reale@gmail.com
 * @version 0.0.1
 * @see     Connection
 */
public interface RemoteServer {
    /**
     * Connects to a server that is listening at the address
     * specified by the <code>address</code> parameter, and returns
     * a reference to a {@link Connection} instance to permit 
     * interacting with that server.
     * <p>
     * If this instance is already in the <i>Connected State</i> this
     * method behaves exactly like {@link #getConnection()}.
     * </p>
     * <p>
     * Once the connection is established this method changes the internal
     * state of the <tt>RemoteServer</tt> instance to reflect
     * the current address and port to wich it is connected
     * </p>
     * @param address an Internet Address locating the desired server
     * @param port the port to connect to
     * @return a reference to the {@link Connection} instance associated
     *         with the established connection
     */
    Connection connect(InetAddress address, int port) throws IOException;
    
    /**
     * Connects to a server that is listening at the address
     * of this <tt>RemoteServer</tt>, and returns
     * a reference to a {@link Connection} instance to permit 
     * interacting with that server.
     * <p>
     * If this instance is already in the <i>Connected State</i> this
     * method behaves exactly like {@link #getConnection()}.
     * </p>
     * @return a reference to the {@link Connection} instance associated
     *         with the established connection
     */
    Connection connect() throws IOException;
    
    /**
     * If a connection with a remote server is currently established,
     * disconnects it and frees the underlying resource. <br />
     * If no connection to the server is established, it does nothing.
     */
    void disconnect();
    
    /**
     * If in the <i>Connected State</i> returns the
     * associated {@link Connection} instance. 
     * <p>
     *   If there is no actual connection with the RemoteServer returns 
     *   <code>null</code>
     * </p>
     * @return the connection to the remote server, or <code>null</code>
     *         if there's no connection
     */
    Connection getConnection();
    
    /**
     * Returns the address currently associated with this <tt>RemoteServer</tt>.
     * <p>
     * If this instance is in the <i>Connected State</i> this address also reflects the 
     * actual address where the server is listening.
     * </p>
     * <p>
     * If in the <i>Disconnected State</i> this address may or may not reflect
     * the real address where the server is listening.
     * </p>
     * @return the address currently associated with this <tt>RemoteServer</tt>.
     */
    InetAddress getAddress();
    
    /**
     * Sets the address associated with this instance of <tt>RemoteSever</tt>.
     * <p>
     * This method should be called only when the instance is in the
     * <i>Disconnected State</i>. <br/>
     * If it is called while in the <i>Connected State</i> it throws a
     * {@link ConnectionStateExeption}
     * </p>
     * @param address the address where the server is listening
     * @throws ConnectionStateException if this method is called while in the
     *                                  <i>Connected State</i>
     */
    void setAddress(InetAddress address) throws ConnectionStateExeption;


    boolean isConnected();
    
}
